<template>


  <el-dialog
      top="20px"
      :title="defaultValue.title"
      :lock-scroll="tableConfig.lockScroll"
      :append-to-body="tableConfig.appendToBody"
      :visible="tableConfig.show"
      @close="tableConfig.show = false"
      :show-close="tableConfig.close"
      :destroy-on-close="tableConfig.destroyOnClose"
      width="1100px">

    <el-form size="small" ref="formBillGroupRef" :rules="checkRule" :model="submitData" label-width="180px">

      <el-form-item label="角色名称" prop="name">
        <el-input v-model.trim="submitData.name" />
      </el-form-item>

      <el-form-item label="角色代码" prop="code">
        <el-input v-model.trim="submitData.code" />
      </el-form-item>

      <el-form-item label="角色说明" prop="description">
        <el-input v-model.trim="submitData.description" type="textarea" />
      </el-form-item>

      <el-form-item label="权限" prop="description">
        <!--<el-input v-model.trim="submitData.resourceIdList" type="textarea" />-->
        <el-tree
          class="tree-line" :indent='0'
          :check-strictly="tree.checkStrictly"
          :data="tree.dataTree"
          :default-checked-keys="tree.defaultCheckedKeys"
          default-expand-all
          node-key="id"
          accordion
          show-checkbox
          :highlight-current="tree.highlightSelect"
          :check-on-click-node="tree.checkClick"
          :expand-on-click-node="tree.expandClickNode"
          ref="treeRoleAuth"
        >
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span>{{ data.name }}</span>
          </span>
        </el-tree>
      </el-form-item>

    </el-form>

    <span slot="footer" class="dialog-footer">
      <el-button plain type="warning" @click="toSaveUpd"
                 v-if="defaultValue.saveUpdSelect !== 'select'">{{ defaultValue.title }}</el-button>
      <el-button plain type="primary" @click="tableConfig.show = false">关闭</el-button>
    </span>

  </el-dialog>


</template>

<script>

  import http from '@/utils/http'
  import {clearInvalid} from "@/utils/utils"

  export default {
    name: "RoleSaveUpd",
    data() {
      return {
        // 表格的默认值
        tableConfig: {
          // 关闭时销毁 Dialog 中的元素
          destroyOnClose: true,
          // 弹出框是否打开
          show: false,
          // 是否显示关闭按钮
          close: true,
          // 下面2个属性解决打开弹出框后没有在最上面显示的问题，导致看到的内容是一半的，需要先将滚动条移到最上面
          lockScroll: false,
          appendToBody: true,
        },
        // 默认值，进入页面后的值
        defaultValue: {
          // 弹出框标题
          title: '查看',
          // 保存还是修改or查看,取值有 select | save | upd
          saveUpdSelect: 'select'
        },
        // 提交的数据
        submitData:{
          name: null,
          code: null,
          description: null,
          // 得到的数据
          resourceIdList: null,
        },
        // 校验规则
        checkRule: {
          name: [{required: true, message: '请输入角色名称', trigger: 'blur'}],
          code: [{required: true, message: '请输入角色代码', trigger: 'blur'}],
          description: [{required: true, message: '请输入角色说明', trigger: 'blur'}],
        },
        // 权限树相关的配置
        tree: {
          // 权限树
          dataTree: [],
          // 是否高亮选中
          highlightSelect: true,
          // 是否在点击节点的时候选中节点，默认值为 false，即只有在点击复选框时才会选中节点。
          checkClick: false,
          // 是否在点击节点的时候展开或者收缩节点， 默认值为 true，如果为 false，则只有点箭头图标的时候才会展开或者收缩节点。
          expandClickNode: false,
          // 父子节点是否不关联，即选中父，子节点会不会自动全部选中,在拿到后端传回的父子数据渲染页面时，我们希望不要关联。checkStrictly = true。页面渲染完成，和用户交互时，我们希望关联。checkStrictly = false
          checkStrictly: false,
          // 默认选中的节点
          defaultCheckedKeys:[],
        },
      }
    },
    methods: {
      /**
       * 获取指定角色的所有的权限ID
       */
      getAuthByRoleId(){
        if (this.defaultValue.saveUpdSelect === 'save'){
          return
        }
        http.post("/power/getAuthByRoleId", {
          roleId: this.submitData.id
        }).then(response => {
          let res = response.data;
          if (!res.success) {
            // 401是token过期跳转的
            if (res.code !== 401) {
              this.$message.error(res.msg);
            }
            return
          }
          if (res.data == null){
            return;
          }
          // 表格数据
          // 第一步先设置 check-strictly绑定的属性为true 为了是解除父子节点的关联（意思就是点击勾选父节点的时候下边的所有子节点都不会选中。）
          this.tree.checkStrictly = true
          // 必须要这样异步处理，否则不生效
          this.$nextTick(() =>{
            this.$refs.treeRoleAuth.setCheckedKeys(res.data)
            this.tree.checkStrictly = false
            }
          )

        }).catch(error => {
          this.$message.error(error.message);
        })
      },
      /**
       * 获取权限树选中的节点
       *   实现树的反选和选中，https://blog.csdn.net/Irene1991/article/details/114969502
       */
      getTreeCheckedNodes(){
        // getCheckedKeys 若节点可被选择（即 show-checkbox 为 true），则返回目前被选中的节点的 key 所组成的数组。
        // 返回目前被选中的节点所组成的数组 (leafOnly, includeHalfChecked) 接收两个 boolean 类型的参数，1. 是否只是叶子节点，默认值为 false 2. 是否包含半选节点，默认值为 false
        // let checkedNodes = this.$refs.treeRoleAuth.getCheckedNodes(false, true)
        let checkedNodes = this.$refs.treeRoleAuth.getCheckedNodes(false, true)
        // 最终得到的节点
        let menuIds = []
        checkedNodes.forEach(nodes => {
          // 遍历每个选中的节点，分别将节点的 id 和 pid 加入 menuIds 数组。node的
          menuIds.push(nodes.id, nodes.parentId)
        })
        // 利用set没有重复的值这一特性, 实现数组去重。Array.form方法可以将 Set 结构转为数组。
        this.submitData.resourceIdList = Array.from(new Set(menuIds))
      },
      /**
       * 获取权限树
       */
      getPowerTree() {
        http.post("/power/getAvailableForAuth", null).then(response => {
          let res = response.data;
          if (!res.success) {
            // 401是token过期跳转的
            if (res.code !== 401) {
              this.$message.error(res.msg);
            }
            return
          }
          // 表格数据
          this.tree.dataTree = res.data
          this.getAuthByRoleId()

        }).catch(error => {
          this.$message.error(error.message);
        })
      },
      /**
       * 初始化操作
       * @param operateType 操作类型,保存还是修改or查看,取值有 select \ save \ upd
       * @param obj 如果是修改和查看，则是详细数据,需要赋值
       */
      init(operateType, obj){
        this.defaultValue.saveUpdSelect = operateType
        this.clearOldData()
        this.getPowerTree()

        if (operateType === 'save'){
          this.defaultValue.title = '新增'

        } else if (operateType === 'upd'){
          this.defaultValue.title = '修改'
          // 要json处理下，否则会影响之前的值
          this.submitData = JSON.parse(JSON.stringify(obj))

        } else {
          // 可能查看
        }

        this.tableConfig.show = true
        // this.$store.commit('navigationListChange', ['开支管理', '账单', this.defaultValue.title])
      },
      /**
       * 清理掉旧数据
       */
      clearOldData(){
        this.submitData = {
          name: null,
          code: null,
          description: null,
          // 得到的数据
          resourceIdList: null,
        }
      },
      /**
       * 是保存还是修改
       */
      toSaveUpd(){
        if (this.defaultValue.saveUpdSelect === 'save'){
          this.saveRole()

        } else if (this.defaultValue.saveUpdSelect === 'upd'){
          this.updRole()

        } else {

        }
      },
      /**
       * 保存角色
       */
      saveRole(){
        this.getTreeCheckedNodes()
        http.post("/role/saveRole", this.submitData).then(response => {
          let res = response.data;
          if (!res.success) {
            // 401是token过期跳转的
            if (res.code !== 401){
              this.$message.error(res.msg);
            }
            return
          }

          this.$message.success("保存成功");
          this.$emit('getRoleHave', null)
          // 关闭弹出框,继续添加
          this.tableConfig.show = false

        }).catch(error => {
          this.$message.error(error.message);
        })
      },
      /**
       * 更新角色
       */
      updRole(){
        clearInvalid(this.submitData)
        this.getTreeCheckedNodes()
        http.post("/role/updRole", this.submitData).then(response => {
          let res = response.data;
          if (!res.success) {
            // 401是token过期跳转的
            if (res.code !== 401){
              this.$message.error(res.msg);
            }
            return
          }

          this.$message.success("更新成功");
          this.$emit('getRoleHave', null)
          // 关闭弹出框
          this.tableConfig.show = false

        }).catch(error => {
          this.$message.error(error.message);
        })
      },
    }
  }
</script>

<style >

/*
添加虚线 start
需要去掉 style 去掉scoped
需要在 el-tree 上添加 class="tree-line" :indent='0' 这2个属性
*/

/*缩进量*/
.tree-line .el-tree-node {
  position: relative;
  padding-left: 16px;
}

/*缩进量*/
.tree-line .el-tree-node__children {
  padding-left: 16px;
}

/*竖线*/
.tree-line .el-tree-node::before {
  content: '';
  height: 100%;
  width: 1px;
  position: absolute;
  left: -3px;
  top: -26px;
  border-width: 1px;
  border-left: 1px dashed #52627c;
}

/*当前层最后一个节点的竖线高度固定*/
.tree-line .el-tree-node:last-child::before {
  height: 38px;
}

/*横线*/
.tree-line .el-tree-node::after {
  content: '';
  width: 24px;
  height: 20px;
  position: absolute;
  left: -3px;
  top: 12px;
  border-width: 1px;
  border-top: 1px dashed #52627c;
}

/*去掉最顶层的虚线，放最下面样式才不会被上面的覆盖了*/
.tree-line > .el-tree-node::after {
  border-top: none;
}
.tree-line > .el-tree-node::before {
  border-left: none;
}

/*展开关闭的icon*/
.tree-line .el-tree-node__expand-icon {
  font-size: 16px;
}
/*叶子节点（无子节点）*/
.tree-line .el-tree-node__expand-icon.is-leaf {
  color: transparent;
}

/*
添加虚线 end
需要去掉 style 去掉scoped
*/

</style>
